#include <fcntl.h>
#include <sys/stat.h>

#include <sys/types.h>
#include <sys/uio.h>
#include <sys/socket.h>
#include <sys/time.h>

#include <netinet/in.h>
#include <arpa/inet.h>

#include <unistd.h>
#include <errno.h>
#include <netdb.h>
#include <signal.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <assert.h>

/* Types */
typedef	struct sockaddr_in		Sockaddr;

/* Constants */
#define TRUE					1
#define FALSE					0
#define MaxWBLength				512
#define MaxWriteBlock			128

/* The multicast group for Replicate Files is 224.1.1.1 */
#define RFGROUP       			0xe0010101
#define	RFPORT					44015

/* Transimission parameter */
#define 	MAX_TRY 			3
#define 	TIMEOUT 			100

/* Packet types */
#define		PACKET_OPEN			0x01
#define		PACKET_ACK			0x02
#define		PACKET_NACK			0x03
#define		PACKET_WB			0x04
#define		PACKET_COMMIT		0x05
#define 	PACKET_COMMITNOW	0x06
#define		PACKET_ABORT		0x07
#define		PACKET_REQDATA		0x08
#define 	PACKET_CLOSE		0x09

/* Event type */
#define		EVENT_NETWORK		0x10
#define		EVENT_TIMEOUT		0x11

typedef	struct {
	unsigned int	messageID;			/* Message ID of the packet */
	unsigned int 	senderIP;			/* Sender's IP address */
	unsigned int	receiverIP;			/* Receiver's IP address, used to mimic unicast */
	unsigned int 	type;				/* The type/descriptor header of the packet */
	int				fd;					/* File descriptor */
	unsigned int	hash;				/* Security hash code, checksum */
	unsigned int	body[256];			/* The packet payload */
}	__attribute__ ((__packed__))	RF244BPacket;

typedef	struct {
	short			eventType;
	RF244BPacket	*eventDetail;		/* for incoming data */
	Sockaddr		eventSource;
}									RFEvent;

typedef struct {
	char			name[128];			/* The file name */
}	__attribute__ ((__packed__))	POPEN;

typedef struct {
	int 			blockSize;			/* Number of bytes of the block */
	int 			byteOffset;			/* Byte offset */	
	char 			buffer[MaxWBLength];		/* Content of the block */
}	__attribute__ ((__packed__))	PWriteBlock;

typedef struct {
	int				num;				/* The number of the write block messages */
}	__attribute__ ((__packed__))	PCommit;

typedef struct {
	int				messageID;			/* The messageID of the write block */
}	__attribute__ ((__packed__))	PReqData;

PWriteBlock		WBBuffer[MaxWriteBlock]; /* Write block buffer 	*/
int				WBBufferSize;		/* The size of the buffer	*/
int 			fileDescriptor;		/* Current file descriptor for client	*/

char			filePath[128];		/* Where committed local copies are to be stored by the server */
char			myFileName[256];	/* The name of the file		*/
int				myFileFd;			/* The real file descriptor of the file */
char			tmpFileName[21];	/* The name of the temporary file */
int				tmpFileFd;			/* The file descriptor of the temp file */

unsigned int	messageID;			/* The messageID of the incoming packet */
unsigned int 	clientIP;			/* The IP address of the client */

unsigned int	myRFPort;			/* The port number 			*/
unsigned int	myIP;				/* My IP address			*/
Sockaddr 		*myAddr;			/* My socket address		*/
Sockaddr 		groupAddr;			/* Group Address used for SendData()	*/
int				mySocket;			/* the Socket used for communication	*/
int				myState;			/* Current state of the server */

int 			TimeZero;			/* The baseline time */

/* server.c */
void openFile (int fd, char *fileName);
void writeBlock (int idx, PWriteBlock *packX);
void commitTry(int size);
void commitFile(void);
void abortFile (void);
void closeFile(void);
void sendACK(void);
void sendNACK(void);
void sendReqData(int idx);
void sendPacket (RF244BPacket *pack);
void ConvertIncoming (RF244BPacket *pack);
unsigned int hashFunc(RF244BPacket *pack);
void netInit(unsigned short portNum);
void NextEvent(RFEvent *event, int socket, int time);
Sockaddr* resolveHost(register char *name);
void RFError(char *s);
void RFWarn(char *s);
void RFDebug(char *s);
int getCurrentTime (void);




